package com.senlingspace.system.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.senlingspace.common.enums.LakalaTradeStateEnum;
import com.senlingspace.common.enums.OrderSource;
import com.senlingspace.common.enums.SnapshotItemType;
import com.senlingspace.common.utils.DateUtils;
import com.senlingspace.common.utils.MoneyUtils;
import com.senlingspace.common.utils.PageUtils;
import com.senlingspace.system.domain.*;
import com.senlingspace.system.domain.vo.TransactionVo;
import com.senlingspace.system.mapper.SlkjOrderMapper;
import com.senlingspace.system.mapper.SlkjOrderPricingSnapshotMapper;
import com.senlingspace.system.mapper.SlkjTicketCategoryMapper;
import com.senlingspace.system.service.SlkjTransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author Administrator
 */
@Service
public class SlkjTransactionServiceImpl implements SlkjTransactionService {
    @Autowired
    private SlkjOrderMapper slkjOrderMapper;
    @Autowired
    private SlkjOrderPricingSnapshotMapper slkjOrderPricingSnapshotMapper;
    @Autowired
    private SlkjTicketCategoryMapper slkjTicketCategoryMapper;

    @Override
    public PageInfo<TransactionVo> selectOrderTransaction(Date startTime, Date endTime, Long shopId, String type,Integer source) {
        List<TransactionVo> transactionVos = new ArrayList<>();
        if (startTime == null) {
            startTime = DateUtils.getStartOfDay(new Date());
        }else {
            startTime = DateUtils.getStartOfDay(startTime);
        }
        if(endTime == null ){
            endTime = DateUtils.getStartOfDay(new Date());
        }else {
            endTime = DateUtils.getStartOfDay(endTime);
        }
        Page<Object> pageExt = PageUtils.startPageExt(true);
        List<SlkjOrder> orders = slkjOrderMapper.selectSlkjOrders(startTime,endTime,shopId,type,source);
        long total = pageExt.getTotal();
        for (SlkjOrder order : orders) {
            TransactionVo transactionVo = new TransactionVo();
            transactionVo.setOrderId(order.getOrderId());
            transactionVo.setOrderNumber(order.getOrderNumber());
            transactionVo.setPaymentTime(order.getPaymentTime());

            if (order.getSource().equals(OrderSource.SHOP.getCode())) {
                transactionVo.setSource(OrderSource.SHOP.getDescription());
            } else if (order.getSource().equals(OrderSource.DOUYIN.getCode())) {
                transactionVo.setSource(OrderSource.DOUYIN.getDescription());
            } else if (order.getSource().equals(OrderSource.MEITUAN.getCode())) {
                transactionVo.setSource(OrderSource.MEITUAN.getDescription());
            } else if (order.getSource().equals(OrderSource.MINI_PROGRAM.getCode())) {
                transactionVo.setSource(OrderSource.MINI_PROGRAM.getDescription());
            }

            transactionVo.setShopName(order.getShopName());

            List<SlkjOrderPricingSnapshot> snapshots = slkjOrderPricingSnapshotMapper.selectByOrder(order.getOrderId());

            Integer goodsQuantity = snapshots.stream()
                    .filter(snapshot -> snapshot.getItemType().equals(SnapshotItemType.GOODS.getCode()))
                    .mapToInt(SlkjOrderPricingSnapshot::getBayQuantity)
                    .sum();

            Map<Long, Long> collect = snapshots.stream()
                    .filter(snapshot -> snapshot.getItemType().equals(SnapshotItemType.TICKET.getCode()))
                    .collect(Collectors.groupingBy(
                            SlkjOrderPricingSnapshot::getTicketCategoryId,
                            Collectors.summingLong(SlkjOrderPricingSnapshot::getBayQuantity)
                    ));

            List<Long> ids = collect.keySet().stream()
                    .collect(Collectors.toList());

            List<SlkjTicketCategory> slkjTicketCategories = slkjTicketCategoryMapper.selectSlkjTicketCategoryByIds(ids);

            // 将 slkjTicketCategories 转换为 Map，以便快速查找
            Map<Long, SlkjTicketCategory> ticketCategoryMap = slkjTicketCategories.stream()
                    .collect(Collectors.toMap(SlkjTicketCategory::getId, tc -> tc));

            // 计算乘积并保存结果
            List<Long> results = collect.entrySet().stream()
                    .filter(entry -> ticketCategoryMap.containsKey(entry.getKey()))
                    .map(entry -> entry.getValue() * ticketCategoryMap.get(entry.getKey()).getQuantity())
                    .collect(Collectors.toList());

            int ticketQuantity = results.stream().mapToInt(Long::intValue).sum();

            if (order.getPaymentStatus().equals(LakalaTradeStateEnum.SUCCESS.name())) {
                transactionVo.setType("售卖");
                transactionVo.setGoodsQuantity(goodsQuantity);
                transactionVo.setTicketQuantity(ticketQuantity);
                transactionVo.setAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));
                transactionVos.add(transactionVo);
            } else if (order.getPaymentStatus().equals(LakalaTradeStateEnum.REFUND.name())) {
                // 设置 endTime 的时分秒部分
                Calendar endCal = Calendar.getInstance();
                endCal.setTime(endTime);
                endCal.set(Calendar.HOUR_OF_DAY, 23);
                endCal.set(Calendar.MINUTE, 59);
                endCal.set(Calendar.SECOND, 59);
                endCal.set(Calendar.MILLISECOND, 999);
                // 设置startTime 的时分秒部分
                Calendar startCal = Calendar.getInstance();
                startCal.setTime(startTime);
                startCal.set(Calendar.HOUR_OF_DAY, 0);
                startCal.set(Calendar.MINUTE, 0);
                startCal.set(Calendar.SECOND, 0);
                startCal.set(Calendar.MILLISECOND, 0);
                // 判断当前订单的支付时间是否在时间范围内
                if (order.getPaymentTime().after(startCal.getTime()) || order.getPaymentTime().equals(startCal.getTime())){
                    // 创建售卖记录
                    TransactionVo sellTransactionVo = new TransactionVo();
                    sellTransactionVo.setOrderNumber(order.getOrderNumber());
                    sellTransactionVo.setPaymentTime(order.getPaymentTime());
                    // sellTransactionVo.setRefundTime(order.getUpdateTime());
                    sellTransactionVo.setSource(transactionVo.getSource());
                    sellTransactionVo.setShopName(order.getShopName());
                    sellTransactionVo.setType("售卖");
                    sellTransactionVo.setGoodsQuantity(goodsQuantity);
                    sellTransactionVo.setTicketQuantity(ticketQuantity);
                    sellTransactionVo.setAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));
                    transactionVos.add(sellTransactionVo);
                }
                // 判断当前订单的退款时间是否在时间范围内
                if (order.getUpdateTime().before(endCal.getTime()) || order.getUpdateTime().equals(endCal.getTime())){
                    // 创建退货记录
                    TransactionVo refundTransactionVo = new TransactionVo();
                    refundTransactionVo.setOrderNumber(order.getOrderNumber());
                    refundTransactionVo.setPaymentTime(order.getPaymentTime());
                    refundTransactionVo.setRefundTime(order.getUpdateTime());
                    refundTransactionVo.setSource(transactionVo.getSource());
                    refundTransactionVo.setShopName(order.getShopName());
                    refundTransactionVo.setType("退货");
                    refundTransactionVo.setGoodsQuantity(goodsQuantity); // 退货门票数量为负数
                    refundTransactionVo.setTicketQuantity(ticketQuantity); // 退货商品数量为负数
                    refundTransactionVo.setAmount(MoneyUtils.fen2Yuan(-order.getActualAmount())); // 退货金额为负数
                    transactionVos.add(refundTransactionVo);
                }
            }
        }
        PageInfo<TransactionVo> pageInfo = new PageInfo<>(transactionVos);
        pageInfo.setList(transactionVos);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(pageExt.getPageNum());
        pageInfo.setPageSize(pageExt.getPageSize());
        return pageInfo;
    }

    @Override
    public List<TransactionVo> exportOrderTransaction(Date startTime, Date endTime, Long shopId, String type, Integer source) {
        List<TransactionVo> transactionVos = new ArrayList<>();
        if (startTime == null) {
            startTime = DateUtils.getStartOfDay(new Date());
        }else {
            startTime = DateUtils.getStartOfDay(startTime);
        }
        if(endTime == null ){
            endTime = DateUtils.getStartOfDay(new Date());
        }else {
            endTime = DateUtils.getStartOfDay(endTime);
        }
        Page<Object> pageExt = PageUtils.startPageExt(true);
        List<SlkjOrder> orders = slkjOrderMapper.selectSlkjOrders(startTime,endTime,shopId,type,source);
        long total = pageExt.getTotal();
        for (SlkjOrder order : orders) {
            TransactionVo transactionVo = new TransactionVo();
            transactionVo.setOrderId(order.getOrderId());
            transactionVo.setOrderNumber(order.getOrderNumber());
            transactionVo.setPaymentTime(order.getPaymentTime());

            if (order.getSource().equals(OrderSource.SHOP.getCode())) {
                transactionVo.setSource(OrderSource.SHOP.getDescription());
            } else if (order.getSource().equals(OrderSource.DOUYIN.getCode())) {
                transactionVo.setSource(OrderSource.DOUYIN.getDescription());
            } else if (order.getSource().equals(OrderSource.MEITUAN.getCode())) {
                transactionVo.setSource(OrderSource.MEITUAN.getDescription());
            } else if (order.getSource().equals(OrderSource.MINI_PROGRAM.getCode())) {
                transactionVo.setSource(OrderSource.MINI_PROGRAM.getDescription());
            }

            transactionVo.setShopName(order.getShopName());

            List<SlkjOrderPricingSnapshot> snapshots = slkjOrderPricingSnapshotMapper.selectByOrder(order.getOrderId());

            Integer goodsQuantity = snapshots.stream()
                    .filter(snapshot -> snapshot.getItemType().equals(SnapshotItemType.GOODS.getCode()))
                    .mapToInt(SlkjOrderPricingSnapshot::getBayQuantity)
                    .sum();

            Map<Long, Long> collect = snapshots.stream()
                    .filter(snapshot -> snapshot.getItemType().equals(SnapshotItemType.TICKET.getCode()))
                    .collect(Collectors.groupingBy(
                            SlkjOrderPricingSnapshot::getTicketCategoryId,
                            Collectors.summingLong(SlkjOrderPricingSnapshot::getBayQuantity)
                    ));

            List<Long> ids = collect.keySet().stream()
                    .collect(Collectors.toList());

            List<SlkjTicketCategory> slkjTicketCategories = slkjTicketCategoryMapper.selectSlkjTicketCategoryByIds(ids);

            // 将 slkjTicketCategories 转换为 Map，以便快速查找
            Map<Long, SlkjTicketCategory> ticketCategoryMap = slkjTicketCategories.stream()
                    .collect(Collectors.toMap(SlkjTicketCategory::getId, tc -> tc));

            // 计算乘积并保存结果
            List<Long> results = collect.entrySet().stream()
                    .filter(entry -> ticketCategoryMap.containsKey(entry.getKey()))
                    .map(entry -> entry.getValue() * ticketCategoryMap.get(entry.getKey()).getQuantity())
                    .collect(Collectors.toList());

            int ticketQuantity = results.stream().mapToInt(Long::intValue).sum();

            if (order.getPaymentStatus().equals(LakalaTradeStateEnum.SUCCESS.name())) {
                transactionVo.setType("售卖");
                transactionVo.setGoodsQuantity(goodsQuantity);
                transactionVo.setTicketQuantity(ticketQuantity);
                transactionVo.setAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));
                transactionVos.add(transactionVo);
            } else if (order.getPaymentStatus().equals(LakalaTradeStateEnum.REFUND.name())) {
                // 设置 endTime 的时分秒部分
                Calendar endCal = Calendar.getInstance();
                endCal.setTime(endTime);
                endCal.set(Calendar.HOUR_OF_DAY, 23);
                endCal.set(Calendar.MINUTE, 59);
                endCal.set(Calendar.SECOND, 59);
                endCal.set(Calendar.MILLISECOND, 999);
                // 设置startTime 的时分秒部分
                Calendar startCal = Calendar.getInstance();
                startCal.setTime(startTime);
                startCal.set(Calendar.HOUR_OF_DAY, 0);
                startCal.set(Calendar.MINUTE, 0);
                startCal.set(Calendar.SECOND, 0);
                startCal.set(Calendar.MILLISECOND, 0);
                // 判断当前订单的支付时间是否在时间范围内
                if (order.getPaymentTime().after(startCal.getTime()) || order.getPaymentTime().equals(startCal.getTime())){
                    // 创建售卖记录
                    TransactionVo sellTransactionVo = new TransactionVo();
                    sellTransactionVo.setOrderNumber(order.getOrderNumber());
                    sellTransactionVo.setPaymentTime(order.getPaymentTime());
                    // sellTransactionVo.setRefundTime(order.getUpdateTime());
                    sellTransactionVo.setSource(transactionVo.getSource());
                    sellTransactionVo.setShopName(order.getShopName());
                    sellTransactionVo.setType("售卖");
                    sellTransactionVo.setGoodsQuantity(goodsQuantity);
                    sellTransactionVo.setTicketQuantity(ticketQuantity);
                    sellTransactionVo.setAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));
                    transactionVos.add(sellTransactionVo);
                }
                // 判断当前订单的退款时间是否在时间范围内
                if (order.getUpdateTime().before(endCal.getTime()) || order.getUpdateTime().equals(endCal.getTime())){
                    // 创建退货记录
                    TransactionVo refundTransactionVo = new TransactionVo();
                    refundTransactionVo.setOrderNumber(order.getOrderNumber());
                    refundTransactionVo.setPaymentTime(order.getPaymentTime());
                    refundTransactionVo.setRefundTime(order.getUpdateTime());
                    refundTransactionVo.setSource(transactionVo.getSource());
                    refundTransactionVo.setShopName(order.getShopName());
                    refundTransactionVo.setType("退货");
                    refundTransactionVo.setGoodsQuantity(goodsQuantity); // 退货门票数量为负数
                    refundTransactionVo.setTicketQuantity(ticketQuantity); // 退货商品数量为负数
                    refundTransactionVo.setAmount(MoneyUtils.fen2Yuan(-order.getActualAmount())); // 退货金额为负数
                    transactionVos.add(refundTransactionVo);
                }
            }
        }
        return transactionVos;
    }
}
